/**
 * @file        usart-stm32f4xx.c
 *
 * @brief       
 *
 * @date        Dec 1, 2012 12:01:45 PM
 *
 * @author      Ashwin Vijayakumar
 *
 * @copyright   (C) 2012 Ashwin Vijayakumar <ashwin@afflatustech.com>
 * @copyright   (C) 2012 Afflatus Techtronics <www.afflatustech.com>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or (at your
 * option) any later version.
 */

/* ---- System headers ------------------------------------------------------ */
#include <errno.h>

/* ---- Local headers ------------------------------------------------------- */
#include "usart-stm32f4xx.h"
#include "stm32f4xx.h"

/* ---- Typedef section (lower_case_type) ----------------------------------- */
/* ---- Constants section (ALL_CAPS) ---------------------------------------- */

/* Modem Control Register Bits */
#define MCR_DTR                 0x01
#define MCR_RTS                 0x02
#define MCR_RESERVED2           0x04
#define MCR_RESERVED3           0x08
#define MCR_RESERVED4           0x10
#define MCR_RESERVED5           0x20
#define MCR_RESERVED6           0x40
#define MCR_RESERVED7           0x80

/* ---- Macros section (ALL_CAPS) ------------------------------------------- */
/* ---- Global variables section (lower_case) ------------------------------- */
/* ---- Function prototypes section (lower_case) ---------------------------- */
/* ---- Getter/setter method section (get/set/is_lower_case) ---------------- */

/**
 * @fn          usart_stm32f4xx_tx_empty
 */
uint16_t
usart_stm32f4xx_tx_empty( usart_port_type* usart_port )
{
  return( usart_port->SR & USART_SR_TXE );
}

/**
 * @fn          usart_stm32f4xx_setmctrl
 * @param       mctrl = [NA|NA|NA|NA|NA|NA|MCR_DTR|MCR_RTS]
 */
void
usart_stm32f4xx_set_mctrl( usart_port_type* usart_port, unsigned int mctrl )
{
  (mctrl & MCR_DTR) ?
      (usart_port->CR3 |= USART_CR3_CTSE) :
      (usart_port->CR3 &= ~USART_CR3_CTSE);

  (mctrl & MCR_RTS) ?
      (usart_port->CR3 |= USART_CR3_RTSE) :
      (usart_port->CR3 &= ~USART_CR3_RTSE);
}

/**
 * @fn          usart_stm32f4xx_get_mctrl
 */
uint16_t
usart_stm32f4xx_get_mctrl( usart_port_type* usart_port )
{
  return( usart_port->CR3 & ( USART_CR3_CTSE | USART_CR3_RTSE) );
}

/**
 * @fn          usart_stm32f4xx_stop_tx
 * @param       usart_stop = 0 => Transmitter is disabled
 *              usart_stop = 1 => Transmitter is enabled
 */
void
usart_stm32f4xx_stop_tx( usart_port_type* usart_port, unsigned int usart_stop )
{
  if( !usart_stop )
    {
      usart_port->CR1 &= ~USART_CR1_TXEIE;
      usart_port->CR1 &= ~USART_CR1_TCIE;
      usart_port->CR1 &= ~USART_CR1_TE;
    }
}

/**
 * @fn          usart_stm32f4xx_start_tx
 * @param       usart_start = 0 => Transmitter is disabled
 *              usart_start = 1 => Transmitter is enabled
 */
void
usart_stm32f4xx_start_tx( usart_port_type* usart_port, unsigned int usart_start )
{
  if( usart_start )
    usart_port->CR1 |= USART_CR1_TE;
}

/**
 * @fn          usart_stm32f4xx_stop_rx
 */
void
usart_stm32f4xx_stop_rx( usart_port_type* usart_port )
{
  usart_port->CR1 &= ~USART_CR1_RXNEIE;
  usart_port->CR1 &= ~USART_CR1_RE;
}

/**
 * @fn          usart_stm32f4xx_break_ctl
 * @param       ctl = 0 => No break character is transmitted
 *              ctl = !0 => Break character will be transmitted
 */
void
usart_stm32f4xx_break_ctl( usart_port_type* usart_port, int ctl )
{
  if( ctl )
    usart_port->CR1 |= USART_CR1_SBK;
}

/**
 * @fn          usart_stm32f4xx_put_char
 * @warning     This function does not check if the TX data register is empty,
 *              it simply overwrites any data that is still not moved into the
 *              shift register. The user should take care of checking it by
 *              using is_usart_stm32f4xx_tdr_empty
 */
void
usart_stm32f4xx_put_char( usart_port_type* usart_port, uint16_t c )
{
  usart_port->DR = ( c & (uint16_t)0x01FF );
}

/**
 * @fn          usart_stm32f4xx_get_char
 * @return      ENODATA => Data is not received
 *              else, the received data
 */
uint16_t
usart_stm32f4xx_get_char( usart_port_type* usart_port )
{
  if( usart_port->SR & USART_SR_RXNE)
    return( (uint16_t)(usart_port->DR & (uint16_t)0x01FF) );
  else
    return( ENODATA );
}

/* ==== End of file ================= Copyright (C) 2012 Afflatus Techtronics */
